Skip to content

Troubleshooting

When working with layout animations, there are tons of little gotchas and common issues. This lesson is essentially a big list of things you can try, if your layout animation isn't doing what you expect.

  • To prevent text from stretching or warping, wrap nested elements in their own Motion component, setting layout to "position":
<motion.div layout={true}>
<motion.p layout="position">
Hello world!
</motion.p>
</motion.div>
  • If the text “snaps” to a new position at the start of the transition, it's likely because the characters themselves are shifting around in their DOM rectangle. Use CSS to shrinkwrap the DOM node around the characters:
<div
style={{
display: 'flex',
justifyContent: 'center',
}}
>
<motion.p>
Centered text
</motion.p>
</div>

(I'm using an inline style here so that it all fits in the same snippet. In reality, you should do this in a CSS Module, or however you typically apply CSS.)

  • If elements appear to dance or jiggle, make sure that any nested motion components use the same transition settings:
<motion.div
transition={CUSTOM_SPRING}
>
<motion.p
transition={CUSTOM_SPRING}
>
Centered text
</motion.p>
</motion.div>
const CUSTOM_SPRING = {
type: 'spring',
stiffness: 300,
damping: 45,
}
  • If the corners appear to twitch during an animation, make sure you're specifying the borderRadius explicitly, using initial:
<motion.div
initial={{
borderRadius: 32,
}}
/>

You can also do the same thing with boxShadow, though it only works with a single shadow.

  • For shared layout animations that seem to teleport around, try wrapping all related elements in a LayoutGroup element:
<LayoutGroup>
<div>
{someCondition && <motion.div layoutId="some-val" />}
</div>
{!someCondition && <motion.div layoutId="some-val" />}
</LayoutGroup>
  • If elements appear to blink out of existence during a shared layout animation, make sure you're using the same value for layoutId and key:
<motion.div
layoutId={layoutId}
- key={index}
+ key={layoutId}
/>
  • When setting the layoutId prop, make sure it's a truthy value (and not 0 or ''):
<motion.div
layoutId={`${uniqueId}-${index}`}
/>

In addition to these gotchas that we've covered, here are some more you might wish to research further, in your own endeavours with Framer Motion:

  • If the element doesn't seem to be animating at all, make sure the element isn't set to display: inline. If you're animating a <span>, <a>, or other inline element, you'll need to set display: block so that it can be transformed.
  • If a layout animation is happening when it shouldn't be (eg. when a different part of the DOM changes), you can use layoutRoot to ignore certain changes.

Check out the full Troubleshooting Guide in the Framer Motion docs.

Onwards!

And so, this marks the end of the bonus module on Framer Motion. I hope you've found it helpful. 😄

In these lessons, I chose to go deep into layout animations, since I think it's the killer feature with Framer Motion. It's worth pointing out, though, that Framer Motion has a bunch of other features as well, including support for lots of different gestures, exit animations, and more.

Even within the narrow slice of layout animations, I've shown you the most critical parts of the API, but there's so much more we can do with them! I hope that I've given you a sense of what's possible with this tool, and that you'll continue to experiment and explore. ✨

You can learn more about Framer Motion in the official docs.